library(rstatix)
library(dplyr)
library(ggplot2)
# A small function helping us to round all numbers (0.123456 -> 0.123)
round_df <- function(df, digits = 3) {
nums <- vapply(df, is.numeric, FUN.VALUE = logical(1))
df[,nums] <- round(df[,nums], digits = digits)
(df)
}
# Loading the CSV file
df <- read.csv("data-wpm-threefactorial.csv")
# Show header if everything is OK
head(df)
# Check if data is normal distributed
round_df(df %>% group_by(Swipe, Visual, Tactile) %>% shapiro_test(WPM))
# Nothing is significant, so we can run a three-way repeated-measures ANOVA
anova <- anova_test(data = df, dv = WPM, wid = SubjectID, within = c(Swipe, Visual, Tactile), effect.size = "pes")
# Auto correction of degree of freedom (if necessary)
get_anova_table(anova, correction = "auto")
# Let's aggregate the data
means <- df %>% group_by(Swipe,Tactile, Visual) %>% summarize(
Mean = mean(WPM),
SD = sd(WPM),
N = n(), .groups = 'drop',) %>% mutate(
SE = SD / sqrt(N),
CI = qt(1 - (0.05 / 2), N - 1) * SE)
# Let's plot the data
plot <- ggplot(means, aes(y=Mean, x=Visual, fill=Swipe)) +
geom_bar(stat = "identity", position = position_dodge(width = 0.8), width=0.75) +
geom_errorbar(aes(ymin=Mean-CI, ymax=Mean+CI, width=.1), position=position_dodge(0.8), width=0.2, size=0.3) +
ylab("words per minute") +
xlab("")+
ggtitle("Typing performance in words per minute (WPM)") +
theme_minimal() +
facet_wrap(Tactile~.) +
scale_fill_manual(values = c("tomato1","steelblue2","gold2", "olivedrab3", "gray70")) +
theme(
legend.margin=margin(t = -5, unit='mm'),
plot.margin=unit(x=c(1,2,1,1),units="mm"),
legend.position = "bottom",
legend.title = element_blank(),
plot.title = element_text(hjust = 0.5),
panel.background = element_rect(size=0.5, color="transparent", fill="gray98" )
)
options(repr.plot.width = 6, repr.plot.height = 4)
plot
ggsave("Swipe-Modality-BarChart.pdf", plot, width=5, height=3.5, device=cairo_pdf)
| SubjectID | Swipe | Visual | Tactile | WPM | |
|---|---|---|---|---|---|
| <int> | <chr> | <chr> | <chr> | <dbl> | |
| 1 | 1 | No Swipe | No Visual Feedback | No Tactile Feedback | 31.36881 |
| 2 | 1 | Swipe | No Visual Feedback | No Tactile Feedback | 45.19973 |
| 3 | 1 | No Swipe | Visual Feedback | No Tactile Feedback | 46.75281 |
| 4 | 1 | Swipe | Visual Feedback | No Tactile Feedback | 62.19684 |
| 5 | 1 | No Swipe | No Visual Feedback | Tactile Feedback | 39.96038 |
| 6 | 1 | Swipe | No Visual Feedback | Tactile Feedback | 43.49072 |
| Swipe | Visual | Tactile | variable | statistic | p |
|---|---|---|---|---|---|
| <chr> | <chr> | <chr> | <chr> | <dbl> | <dbl> |
| No Swipe | No Visual Feedback | No Tactile Feedback | WPM | 0.967 | 0.424 |
| No Swipe | No Visual Feedback | Tactile Feedback | WPM | 0.984 | 0.904 |
| No Swipe | Visual Feedback | No Tactile Feedback | WPM | 0.974 | 0.624 |
| No Swipe | Visual Feedback | Tactile Feedback | WPM | 0.981 | 0.828 |
| Swipe | No Visual Feedback | No Tactile Feedback | WPM | 0.981 | 0.817 |
| Swipe | No Visual Feedback | Tactile Feedback | WPM | 0.988 | 0.976 |
| Swipe | Visual Feedback | No Tactile Feedback | WPM | 0.958 | 0.248 |
| Swipe | Visual Feedback | Tactile Feedback | WPM | 0.978 | 0.725 |
| Effect | DFn | DFd | F | p | p<.05 | pes | |
|---|---|---|---|---|---|---|---|
| <chr> | <dbl> | <dbl> | <dbl> | <dbl> | <chr> | <dbl> | |
| 1 | Swipe | 1 | 31 | 52.755 | 3.59e-08 | * | 0.630 |
| 2 | Visual | 1 | 31 | 323.981 | 5.74e-18 | * | 0.913 |
| 3 | Tactile | 1 | 31 | 0.882 | 3.55e-01 | 0.028 | |
| 4 | Swipe:Visual | 1 | 31 | 0.645 | 4.28e-01 | 0.020 | |
| 5 | Swipe:Tactile | 1 | 31 | 8.728 | 6.00e-03 | * | 0.220 |
| 6 | Visual:Tactile | 1 | 31 | 2.295 | 1.40e-01 | 0.069 | |
| 7 | Swipe:Visual:Tactile | 1 | 31 | 0.528 | 4.73e-01 | 0.017 |
# Execute code above first
# Loading the CSV file with the TLX subscores
df <- read.csv("data-tlx-threefactorial.csv")
# TLX = Mental Demand + Phyiscal Demand + Temporal Demand + Performance + Effort + Frustration
df$TLX <- df$MD + df$PD + df$TD + df$PE + df$EF + df$FR
# Check the head
head(df)
# Check if data is normal distributed
round_df(df %>% group_by(Swipe, Visual, Tactile) %>% shapiro_test(TLX))
# One is significant, however, we still assume normality and run a three-way repeated-measures ANOVA
anova <- anova_test(data = df, dv = TLX, wid = SubjectID, within = c(Swipe, Visual, Tactile), effect.size = "pes")
# Auto correction of degree of freedom (if necessary)
get_anova_table(anova, correction = "auto")
# Let's aggregate the data
means <- df %>% group_by(Swipe,Tactile, Visual) %>% summarize(
Mean = mean(TLX),
SD = sd(TLX),
N = n(), .groups = 'drop',) %>% mutate(
SE = SD / sqrt(N),
CI = qt(1 - (0.05 / 2), N - 1) * SE)
# Let's plot the data
plot <- ggplot(means, aes(y=Mean, x=Visual, fill=Swipe)) +
geom_bar(stat = "identity", position = position_dodge(width = 0.8), width=0.75) +
geom_errorbar(aes(ymin=Mean-CI, ymax=Mean+CI, width=.1), position=position_dodge(0.8), width=0.2, size=0.3) +
ylab("score") +
xlab("")+
ggtitle("Workload (RTLX)") +
theme_minimal() +
facet_wrap(Tactile~.) +
scale_fill_manual(values = c("tomato1","steelblue2","gold2", "olivedrab3", "gray70")) +
theme(
legend.margin=margin(t = -5, unit='mm'),
plot.margin=unit(x=c(1,2,1,1),units="mm"),
legend.position = "bottom",
legend.title = element_blank(),
plot.title = element_text(hjust = 0.5),
panel.background = element_rect(size=0.5, color="transparent", fill="gray98" )
)
options(repr.plot.width = 6, repr.plot.height = 4)
plot
ggsave("Swipe-Modality-BarChart.pdf", plot, width=5, height=3.5, device=cairo_pdf)
| SubjectID | Sequence | Swipe | Visual | Tactile | MD | PD | TD | PE | EF | FR | TLX | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| <int> | <int> | <chr> | <chr> | <chr> | <int> | <int> | <int> | <int> | <int> | <int> | <int> | |
| 1 | 1 | 1 | No Swipe | No Visual Feedback | No Tactile Feedback | 0 | 3 | 6 | 0 | 9 | 5 | 23 |
| 2 | 1 | 2 | Swipe | No Visual Feedback | No Tactile Feedback | 2 | 14 | 7 | 7 | 0 | 4 | 34 |
| 3 | 1 | 3 | Swipe | Visual Feedback | Tactile Feedback | 10 | 10 | 10 | 8 | 6 | 6 | 50 |
| 4 | 1 | 4 | No Swipe | Visual Feedback | No Tactile Feedback | 7 | 2 | 3 | 4 | 0 | 6 | 22 |
| 5 | 1 | 5 | No Swipe | Visual Feedback | Tactile Feedback | 4 | 8 | 1 | 6 | 3 | 7 | 29 |
| 6 | 1 | 6 | Swipe | Visual Feedback | No Tactile Feedback | 5 | 9 | 1 | 4 | 6 | 3 | 28 |
| Swipe | Visual | Tactile | variable | statistic | p |
|---|---|---|---|---|---|
| <chr> | <chr> | <chr> | <chr> | <dbl> | <dbl> |
| No Swipe | No Visual Feedback | No Tactile Feedback | TLX | 0.964 | 0.359 |
| No Swipe | No Visual Feedback | Tactile Feedback | TLX | 0.961 | 0.294 |
| No Swipe | Visual Feedback | No Tactile Feedback | TLX | 0.984 | 0.898 |
| No Swipe | Visual Feedback | Tactile Feedback | TLX | 0.986 | 0.951 |
| Swipe | No Visual Feedback | No Tactile Feedback | TLX | 0.926 | 0.031 |
| Swipe | No Visual Feedback | Tactile Feedback | TLX | 0.979 | 0.783 |
| Swipe | Visual Feedback | No Tactile Feedback | TLX | 0.968 | 0.439 |
| Swipe | Visual Feedback | Tactile Feedback | TLX | 0.971 | 0.530 |
| Effect | DFn | DFd | F | p | p<.05 | pes | |
|---|---|---|---|---|---|---|---|
| <chr> | <dbl> | <dbl> | <dbl> | <dbl> | <chr> | <dbl> | |
| 1 | Swipe | 1 | 31 | 137.540 | 6.25e-13 | * | 0.816 |
| 2 | Visual | 1 | 31 | 4.351 | 4.50e-02 | * | 0.123 |
| 3 | Tactile | 1 | 31 | 63.589 | 5.29e-09 | * | 0.672 |
| 4 | Swipe:Visual | 1 | 31 | 1.069 | 3.09e-01 | 0.033 | |
| 5 | Swipe:Tactile | 1 | 31 | 15.002 | 5.19e-04 | * | 0.326 |
| 6 | Visual:Tactile | 1 | 31 | 29.158 | 6.82e-06 | * | 0.485 |
| 7 | Swipe:Visual:Tactile | 1 | 31 | 3.993 | 5.50e-02 | 0.114 |